#include"cal.h"
#include<iostream>
#include<queue>
#include<stack>

double calculate(std::queue<char> &exp){   
    /**
     * @brief nums以栈形式存放exp队列中的浮点数.
     * 
     * 当遇到某一个运算符时,取出nums里的两个元素,
     * 进行相应运算后的结果存回栈中.
     */
    std::stack<double> nums;

    while(!exp.empty()){
        /**
         * 以下创建了一个字符数组,用于存放一个浮点数的字符串表示
         * 
         * @attention 这里由于要动态分配内存,但不清楚
         * 当前浮点数对应的字符串长度,因此干脆将分配内存的大小
         * 直接规定为队列长度,不过代价是浪费了一些内存.
         */
        int n = exp.size(); //有些浪费内存
        char* str = new char[n];//分配内存空间

        int num_size = 0;   //若正在读取浮点数,
                            //则准备记录其对应字符串长度
        
        /**
         * 由于传入的队列有人为添加的空格来间隔每个浮点数,
         * 因此还要判断在遇到空格时中断循环,
         * 并准备给字符串长度重新赋值.
         */
        while(!exp.empty() && exp.front() != ' '){
            char c = exp.front();   //读取队列第一个元素

            /**
             * 如果正在读取浮点数,则将其存入字符数组str,
             * 且对应字符串长度(num_size)+1.
             */
            if((c >= '0' && c <= '9') || c == '.')
            {
                str[num_size++] = exp.front();
            }

            /**
             * 如果正在读取运算符,则对nums顶上的两个数
             * 进行运算操作
             */
            if(c == '+' || c == '-' ||
               c == '*' || c == '/')
            {
                double a = nums.top();
                nums.pop();
                switch (c)
                {
                case '+':
                    nums.top() += a;
                    break;

                case '-':
                    nums.top() -= a;
                    break;
                
                case '*':
                    nums.top() *= a;
                    break;

                case '/':
                    nums.top() /= a;
                    break;

                default:
                    break;
                }
            }

            exp.pop();  //读取exp中的元素后让其出队.      
        }

        /**
         * 判断字符数组str是否有存入浮点数,
         * 若num_size>0说明有存入,
         * 需要将str转化为浮点数并使其进栈nums.
         */
        if(num_size != 0)
            /*atof函数:将字符数组str转化为浮点数*/
            nums.push(atof(str));

        /**
         * 若循环不是因为队列为空而中断,
         * 当它是因为空格中断时,此时需要去除它.
         */
        if(!exp.empty() && exp.front() == ' ')
            exp.pop();//去除人为添加的空格
        
        /*释放内存*/
        if(str != nullptr)
            delete [] str;
    }

    return nums.top();  //返回nums栈顶元素
}